package com.cy.mall.web.front.customer;

import java.util.List;
import java.util.Map;

import com.cy.mall.comm.constant.Constants;
import com.cy.mall.comm.utils.CommonUtils;
import com.cy.mall.comm.utils.JsonObjectMapper;
import com.cy.mall.comm.utils.RSAUtils;
import com.cy.mall.model.PageBean;
import com.cy.mall.model.ao.customer.*;
import com.cy.mall.model.domain.customer.CustomerBank;
import com.cy.mall.model.domain.customer.CustomerIdCardAuthRecord;
import com.cy.mall.model.dto.bigdata.BigDataCheckParamDTO;
import com.cy.mall.model.dto.customer.IdCardOcrResultSaveDTO;
import com.cy.mall.model.dto.fujue.req.AuthDataDTO;
import com.cy.mall.model.dto.fujue.req.GetH5UrlParamDTO;
import com.cy.mall.model.dto.fujue.resp.AuthStatusRespDTO;
import com.cy.mall.model.enums.IdCardType;
import com.cy.mall.model.enums.ResultCode;
import com.cy.mall.model.enums.customer.CustomerIdCardAuthStatus;
import com.cy.mall.model.enums.customer.CustomerImageType;
import com.cy.mall.model.enums.fujue.FujueH5Type;
import com.cy.mall.model.query.customer.CustomerInviteListQuery;
import com.cy.mall.model.vo.customer.*;
import com.cy.mall.service.comm.*;
import com.cy.mall.service.fujue.FujueApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.cy.mall.comm.exception.MsgException;
import com.cy.mall.model.Result;
import com.cy.mall.model.domain.customer.Customer;
import com.cy.mall.model.dto.bank.BankCardVerifyParamDTO;
import com.cy.mall.model.dto.customer.CustomerLoginDTO;
import com.cy.mall.model.dto.customer.ValidateFaceIdResultDTO;
import com.cy.mall.model.enums.CheckResult;
import com.cy.mall.model.enums.SmsType;
import com.cy.mall.service.customer.CustomerService;
import com.cy.mall.web.BaseController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.multipart.MultipartFile;

/**
 * 前台-客户
 *
 * @author tanyilin
 *
 * @create 2019年2月27日 上午11:22:54
 */
@Slf4j
@RestController
@RequestMapping("/customer")
@Api(tags = "前台-客户")
public class CustomerController extends BaseController {

	@Autowired
	private CustomerService          customerService;
	@Autowired
	private FaceIDCertificateService faceIDCertificateService;
	@Autowired
	private BankCardService          bankCardService;
	@Autowired
	private BigDataService           bigDataService;
	@Autowired
	private FileUploadService fileUploadService;
	@Autowired
	private OcrIdCardService ocrIdCardService;
	@Autowired
	private FujueApiService fujueApiService;
	
	@ApiOperation("验证用户是否已进行人脸识别并通过")
	@GetMapping("/validate/faceid/result")
	public Result<CustomerLoginDTO> validateFaceIdResult() {
		
		CustomerLoginDTO customerLoginDTO = this.getLoginCustomer();
		ValidateFaceIdResultDTO validateFaceIdResultDTO = customerService.validateFaceIdResult(customerLoginDTO.getCustomerId());
		//更新人脸识别的结果状态到dto里
		customerLoginDTO.setFaceidCheckResult(validateFaceIdResultDTO.getFaceidCheckResult());
		customerLoginDTO.setCustomerName(validateFaceIdResultDTO.getCustomerName());
		customerLoginDTO.setIdNo(validateFaceIdResultDTO.getIdNo());
		String faceIDLiteUrl = "";
		if(!CheckResult.PASS.equals(validateFaceIdResultDTO.getFaceidCheckResult())) {
			//如果未进行faceid人脸识别，或者人脸识别失败过的，则进入人脸识别流程
			Result<Map<String, Object>> getBizTokenResult = faceIDCertificateService.getBizToken();
			if(!getBizTokenResult.isOk()) {
				throw new MsgException("请求获取人脸识别 biz_token 失败");
			}
			//得到 biz_token、url
			Map<String, Object> map = getBizTokenResult.getData();
			String bizToken = map.get("BizToken").toString(); 
			faceIDLiteUrl = map.get("Url").toString(); 
			
			//更新biz_token
			customerService.updateBizToken(customerLoginDTO.getCustomerId(), bizToken);
			
		}
		//激活客户登录信息有效时间
		this.expireCustomerLoginDTO(customerLoginDTO.getToken() , customerLoginDTO);
		
		customerLoginDTO.setFaceIDLiteUrl(faceIDLiteUrl);
		
		return ok("", customerLoginDTO);
	} 
	
	@ApiOperation("确认还款卡(暂废弃)")
	@PostMapping("/do/confirm/bank/card1")
	public Result doConfirmBankCard(@Validated ConfirmBankCardAO confirmBankCardAO, BindingResult bindingResult) {
		
		//检验参数、验证码
		this.checkError(bindingResult);
		this.checkSmsCode(confirmBankCardAO.getBankMobile(), confirmBankCardAO.getSmsCode(), SmsType.BINDCARD);
		
		//查询客户信息
		Long customerId = this.getLoginCustomer().getCustomerId();
		Customer customer = customerService.selectCustomerByPrimaryKey(customerId);
		
		//封装查询参数
		BankCardVerifyParamDTO bankCardVerifyParamDTO = new BankCardVerifyParamDTO();
		bankCardVerifyParamDTO.setMobile(confirmBankCardAO.getBankMobile());
		bankCardVerifyParamDTO.setBankcard(confirmBankCardAO.getBankCard());
		bankCardVerifyParamDTO.setCardNo(customer.getIdNo());
		bankCardVerifyParamDTO.setRealName(customer.getName());
		
		//验证银行卡四要素
		Result verifyResult = bankCardService.verifyBankCard(bankCardVerifyParamDTO);
		if(!verifyResult.isOk()) {
			return verifyResult;
		}
		
		//查询银行卡归属地信息
		Result queryResult = bankCardService.queryBankCard(confirmBankCardAO.getBankCard());
		if (!queryResult.isOk()) {
			return queryResult;
		}
		//得到银行卡信息
		Map<String, Object> queryResultMap = (Map) queryResult.getData();
		String bankNo = queryResultMap.get("banknum").toString();
		String bankName = queryResultMap.get("bankname").toString();
		
		//更新客户的还款卡信息
		Customer updateCustomer = new Customer();
		updateCustomer.setId(customerId);
		updateCustomer.setBankNo(bankNo);
		updateCustomer.setBankName(bankName);
		updateCustomer.setBankCard(confirmBankCardAO.getBankCard());
		updateCustomer.setBankMobile(confirmBankCardAO.getBankMobile());
		customerService.updateCustomer(updateCustomer);
		
		return ok("确认还款卡成功");
		
	}

	@ApiOperation("测试银行卡四要素验证(暂废弃)")
	@PostMapping("/test/bankcard/verify")
	public Result testVerifyBankcard(BankCardVerifyParamDTO bankCardVerifyParamDTO) {
		//验证银行卡四要素
		Result verifyResult = bankCardService.verifyBankCard(bankCardVerifyParamDTO);
		return verifyResult;
	}

	@ApiOperation("测试查询客户大数据(暂废弃)")
	@GetMapping("/check/bigdata")
	public Result checkBigData() {
		Long customerId = this.getLoginCustomer().getCustomerId();
		Customer customer = customerService.selectCustomerByPrimaryKey(customerId);
		BigDataCheckParamDTO paramDTO = new BigDataCheckParamDTO();
		paramDTO.setName(customer.getName());
		paramDTO.setIdCard(customer.getIdNo());
		paramDTO.setMobile(customer.getMobile());

		Result bigDataCheckResult = bigDataService.check(paramDTO);

		//请求大数据查询成功，根据风控规则判断客户是否通过，并更新客户大数据查询结果信息表
		Map<String, Object> dataMap = (Map) bigDataCheckResult.getData();
		Result judgeResult = customerService.judgeBigDataCheckResult(dataMap, customerId);
		return bigDataCheckResult;

	}

	@ApiOperation("我的信息")
	@GetMapping("/get/my/info")
	public Result<CustomerMyInfoVO> getMyInfo() {
		CustomerMyInfoVO result = customerService.selectCustomerMyInfoVO(this.getLoginCustomer().getCustomerId());
		return ok("", result);
	}

	@ApiOperation("设置信息")
	@PostMapping("/do/update/info")
	public Result doUpdateInfo(UpdateCustomerAO updateCustomerAO) {

		Customer customer = new Customer();
		BeanUtils.copyProperties(updateCustomerAO, customer);
		customer.setId(this.getLoginCustomer().getCustomerId());
		customerService.updateCustomer(customer);

		return ok();
	}

	@ApiOperation("我的-邀请人数列表")
	@GetMapping("/get/my/inviteList")
	public PageBean<CustomerInviteListVO> getMyInviteCustomerList(CustomerInviteListQuery query) {
		query.setCustomerId(this.getLoginCustomer().getCustomerId());
		PageBean<CustomerInviteListVO> pageBean = customerService.selectCustomerInviteList(query);
		return pageBean;
	}

	@ApiOperation("查询客户已上传并ocr识别出来的身份证信息")
	@GetMapping("/get/idCard/info")
	public Result<CustomerIdCardInfoVO> getCustomerIdCardInfo() {

		CustomerIdCardInfoVO idCardInfo = customerService.getCustomerIdCardInfo(this.getLoginCustomer().getCustomerId());
		return ok("查询成功", idCardInfo);
	}

	@ApiOperation("验证用户是否已完成实名实人验证")
	@GetMapping("/validate/idCard/result")
	public Result validateIdCardResult() {

		return customerService.validateIdCardResult(this.getLoginCustomer().getCustomerId());
	}

	@ApiOperation("上传身份证人像面")
	@PostMapping("/upload/idCard/face")
	public Result uploadIdCardFace(@RequestParam(value = "file") MultipartFile file) {

		long fileLength = file.getSize();
		if(fileLength > 1.5 * 1024 * 1024) {
			return Result.fail("身份证图片大小不可超过1.5MB");
		}
		Long customerId = this.getLoginCustomer().getCustomerId();
		//上传至oss服务器
		String directory = "attachment/customer/" + customerId + "/";
		Result<Map<String, String>> uploadResult = fileUploadService.uploadImage(file, directory, null);
		if(!uploadResult.isOk()) {
			return uploadResult;
		}
		Map<String, String> uploadResultMap = uploadResult.getData();
		String path = uploadResultMap.get("path");
		String src = uploadResultMap.get("src");

		//ocr认证
		Result<Map<String, Object>> ocrResult = ocrIdCardService.doOcrIdCard(src, IdCardType.FACE);
		if(!ocrResult.isOk()) {
			return ocrResult;
		}
		Map<String, Object> ocrResultMap = ocrResult.getData();
		IdCardOcrResultSaveDTO idCardOcrResultSaveDTO = JsonObjectMapper.read(JsonObjectMapper.toJson(ocrResultMap), IdCardOcrResultSaveDTO.class);

		CustomerImageAddAO imageAddAO = new CustomerImageAddAO();
		imageAddAO.setType(CustomerImageType.ID_CARD_FACE);
		imageAddAO.setName("身份证人像面");
		imageAddAO.setPath(path);

		customerService.doSaveIdCardOcrResult(idCardOcrResultSaveDTO, imageAddAO, customerId);

		CustomerIdCardInfoVO idCardInfo = new CustomerIdCardInfoVO();
		idCardInfo.setName(idCardOcrResultSaveDTO.getName());
		idCardInfo.setIdNo(idCardOcrResultSaveDTO.getNum());

		return ok("身份证人像面识别成功", idCardInfo);
	}

	@ApiOperation("上传身份证国徽面")
	@PostMapping("/upload/idCard/back")
	public Result uploadIdCardBack(@RequestParam(value = "file") MultipartFile file) {

		Long customerId = this.getLoginCustomer().getCustomerId();
		CustomerIdCardAuthRecord dbCustomerIdCardAuthRecord = customerService.getCustomerIdCardAuthRecord(customerId);
		if(dbCustomerIdCardAuthRecord == null) {
			return fail("请先上传身份证人像面。");
		}

		long fileLength = file.getSize();
		if(fileLength > 1.5 * 1024 * 1024) {
			return Result.fail("身份证图片大小不可超过1.5MB");
		}
		//上传至oss服务器
		String directory = "attachment/customer/" + customerId + "/";
		Result<Map<String, String>> uploadResult = fileUploadService.uploadImage(file, directory, null);
		if(!uploadResult.isOk()) {
			return uploadResult;
		}
		Map<String, String> uploadResultMap = uploadResult.getData();
		String path = uploadResultMap.get("path");
		String src = uploadResultMap.get("src");

		//ocr认证
		Result<Map<String, Object>> ocrResult = ocrIdCardService.doOcrIdCard(src, IdCardType.BACK);
		if(!ocrResult.isOk()) {
			return ocrResult;
		}
		Map<String, Object> ocrResultMap = ocrResult.getData();
		IdCardOcrResultSaveDTO idCardOcrResultSaveDTO = JsonObjectMapper.read(JsonObjectMapper.toJson(ocrResultMap), IdCardOcrResultSaveDTO.class);

		CustomerImageAddAO imageAddAO = new CustomerImageAddAO();
		imageAddAO.setType(CustomerImageType.ID_CARD_BACK);
		imageAddAO.setName("身份证国徽面");
		imageAddAO.setPath(path);

		customerService.doSaveIdCardOcrResult(idCardOcrResultSaveDTO, imageAddAO, customerId);

		CustomerIdCardInfoVO idCardInfo = new CustomerIdCardInfoVO();
		idCardInfo.setAuthority(idCardOcrResultSaveDTO.getIssue());
		idCardInfo.setValidityStartDate(idCardOcrResultSaveDTO.getStart_date().substring(0, 4).concat(".").concat(idCardOcrResultSaveDTO.getStart_date().substring(4, 6)).concat(".").concat(idCardOcrResultSaveDTO.getStart_date().substring(6)));
		idCardInfo.setValidityEndDate(idCardOcrResultSaveDTO.getEnd_date().substring(0, 4).concat(".").concat(idCardOcrResultSaveDTO.getEnd_date().substring(4, 6)).concat(".").concat(idCardOcrResultSaveDTO.getEnd_date().substring(6)));

		return ok("身份证国徽面识别成功", idCardInfo);
	}

	@ApiOperation("请求云科人脸识别h5页面url")
	@GetMapping("/get/faceVerify/h5/url")
	public Result getFaceVerifyH5Url() {

		Long customerId = this.getLoginCustomer().getCustomerId();
		//获取人脸识别参数
		AuthDataDTO authData = customerService.getCustomerAuthDataDTO(customerId);
		if(CommonUtils.objectFieldsIsEmpty(authData)) {
			return fail("身份证识别参数不全，请重新上传清晰的图片进行识别。");
		}

		//先查询云科的实名认证状态
		Result authResult = this.queryAuthStatus();
		AuthStatusRespDTO authStatusRespDTO = (AuthStatusRespDTO) authResult.getData();
		if("1".equals(authStatusRespDTO.getStatus()) || "2".equals(authStatusRespDTO.getStatus())) {
			//如果是：1-已实名无在途，2-实名有在途不准入；则不用调用云科的实名页面
			return ok("客户已完成实名实人验证", ResultCode.CUSTOMER_ID_CARD_AUTH_SUCCESS);
		}

		//封装请求参数
		GetH5UrlParamDTO getH5UrlParamDTO = new GetH5UrlParamDTO();
		getH5UrlParamDTO.setH5Type(FujueH5Type.FACE_VERIFY.getValue());
		getH5UrlParamDTO.setAuthData(authData);
		//调用api
		Result<Map<String, Object>> result = fujueApiService.getH5Url(getH5UrlParamDTO);
		if(!result.isOk()) {
			return result;
		}
		//对返回数据进行 RSA解密
		Map<String, Object> bodyMap = result.getData();
		String encryptData = String.valueOf(bodyMap.get("data"));
		log.info("获取人脸识别h5页面 api，返回参数data密文：{}", encryptData);
		String decryptData = RSAUtils.privateDecrypt(encryptData, Constants.FUJUE_RSA_PRIVATE_KEY);
		log.info("获取人脸识别h5页面 api，返回参数data明文：{}", decryptData);
		//解析data
		Map<String, Object> dataMap = JsonObjectMapper.read(decryptData, Map.class);

		//更新人脸识别实名认证状态
		customerService.updateCustomerIdCardAuthStatus(customerId, CustomerIdCardAuthStatus.AUTHING);

		return ok("获取h5Url成功", dataMap);
	}

	@ApiOperation("查询客户在云科的人脸识别状态")
	@GetMapping("/query/authStatus")
	public Result queryAuthStatus() {

	    Long customerId = this.getLoginCustomer().getCustomerId();
		CustomerIdCardAuthRecord dbCustomerIdCardAuthRecord = customerService.getCustomerIdCardAuthRecord(customerId);
		if(dbCustomerIdCardAuthRecord == null) {
			return fail("客户实名信息异常。");
		}
		//调用api
		Result<Map<String, Object>> result = fujueApiService.queryAuthStatus(dbCustomerIdCardAuthRecord.getIdNo());
		if(!result.isOk()) {
			return result;
		}
		//对返回数据进行 RSA解密
		Map<String, Object> bodyMap = result.getData();
		String encryptData = String.valueOf(bodyMap.get("data"));
		log.info("获取人脸识别h5页面 api，返回参数data密文：{}", encryptData);
		String decryptData = RSAUtils.privateDecrypt(encryptData, Constants.FUJUE_RSA_PRIVATE_KEY);
		log.info("获取人脸识别h5页面 api，返回参数data明文：{}", decryptData);
        //解析data
        AuthStatusRespDTO authStatusRespDTO = JsonObjectMapper.read(decryptData, AuthStatusRespDTO.class);

        //更新人脸识别状态
        customerService.doUpdateCustomerAuthStatus(authStatusRespDTO, dbCustomerIdCardAuthRecord);

		return ok("查询客户在云科的人脸识别状态完成", authStatusRespDTO);
	}

	@ApiOperation("查询客户的申请信息填写状态")
	@GetMapping("/query/applyInfo/status")
	public Result<CustomerApplyInfoStatusVO> queryCustomerApplyInfoStatus() {

		CustomerApplyInfoStatusVO statusVO = customerService.queryCustomerApplyInfoStatus(this.getLoginCustomer().getCustomerId());
		return ok("查询成功", statusVO);
	}

	@ApiOperation("获取房屋信息")
	@GetMapping("/get/house/info")
	public Result<CustomerHouseInfoDetailVO> getCustomerHouseInfoDetail() {

		CustomerHouseInfoDetailVO detailVO = customerService.getCustomerHouseInfoDetail(this.getLoginCustomer().getCustomerId());
		return ok("查询成功", detailVO);
	}

	@ApiOperation("保存房屋信息")
	@PostMapping("/do/save/house/info")
	public Result doSaveCustomerHouseInfo(@Validated CustomerHouseInfoSaveAO saveAO, BindingResult bindingResult) {

		this.checkError(bindingResult);

		customerService.doSaveCustomerHouseInfo(saveAO, this.getLoginCustomer().getCustomerId());

		return ok("保存房屋信息成功");

	}

	@ApiOperation("获取联系人信息")
	@GetMapping("/get/contact/info")
	public Result<List<CustomerContactInfoVO>> getCustomerContactInfo() {

		List<CustomerContactInfoVO> list = customerService.getCustomerContactInfo(this.getLoginCustomer().getCustomerId());
		return ok("查询成功", list);
	}

	@ApiOperation("保存联系人信息")
	@PostMapping("/do/save/contact/info")
	public Result doSaveCustomerContactInfo(@RequestBody @Validated CustomerContactInfoSaveAO saveAO, BindingResult bindingResult) {

		this.checkError(bindingResult);

		customerService.doSaveCustomerContactInfo(saveAO, this.getLoginCustomer().getCustomerId());

		return ok("保存联系人信息成功");
	}

	@ApiOperation("我的银行卡列表")
	@GetMapping("/get/bank/list")
	public Result<List<CustomerBank>> getBankList() {

		List<CustomerBank> bankList = customerService.getBankList(this.getLoginCustomer().getCustomerId());

		return ok("获取成功", bankList);

	}


}
